package com.ly.nethub.utils

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch


typealias TaskFunc<T> = suspend CoroutineScope.() -> T?

/**
 * 单线程协程构建器，负责重连和心跳
 */
class CoroutineFactory {

    private val ioThreadCoroutine
        get() = CoroutineScope(Dispatchers.IO + SupervisorJob())

    private var bossScope: CoroutineScope? = null //负责重连

    private var workScope: CoroutineScope? = null //负责心跳,数据处理等

    private fun initBossScope() = synchronized(this) {
        if (bossScope == null || bossScope?.isActive == false) {
            bossScope = ioThreadCoroutine
        }
    }

    private fun initWorkScope() = synchronized(this) {
        if (workScope == null || workScope?.isActive == false) {
            workScope = ioThreadCoroutine
        }
    }


    suspend fun <T> executeBossTask(block: TaskFunc<T>): T? {
        initBossScope()
        return bossScope?.async { block() }?.await()
    }

    fun <T> enqueueBossTask(result: (T?) -> Unit = {}, block: TaskFunc<T>): Job? {
        initBossScope()
        return bossScope?.launch {
            result(block())
        }
    }

    suspend fun <T> executeWorkTask(block: TaskFunc<T>): T? {
        initWorkScope()
        return workScope?.async { block() }?.await()
    }

    fun <T> enqueueWorkTask(result: (T?) -> Unit = {}, block: TaskFunc<T>): Job? {
        initWorkScope()
        return workScope?.launch {
            result(block())
        }
    }

    internal fun destroyBossScope() = synchronized(this) {
        LogUtils.d("destroyBossScope")
        bossScope?.cancel()
        bossScope = null
    }

    internal fun destroyWorkScope() = synchronized(this) {
        LogUtils.d("destroyWorkScope")
        workScope?.cancel()
        workScope = null
    }

    fun destroy() {
        destroyBossScope()
        destroyWorkScope()
    }
}